#include "Mutex.hpp"
#include <iostream>
#include <pthread.h>
#include <unistd.h>

int tickets = 1000;

void* Routine1(void* args)
{
    std::string name = static_cast<const char*>(args);
    std::cout << "线程: " << name << " 开始抢票" << std::endl;

    while(1)
    {
        if(tickets > 0)
        {
            usleep(100);
            std::cout << "线程" << name << "抢" << tickets << std::endl;
            tickets--;   
        }
        else
            break;
    }

    return nullptr;
}


//无锁情况下的抢票
void test01()
{

    pthread_t tid1, tid2, tid3;
    
    pthread_create(&tid1, nullptr, Routine1, (void*)"thread-1");
    
    pthread_create(&tid2, nullptr, Routine1, (void*)"thread-2");

    pthread_create(&tid3, nullptr, Routine1, (void*)"thread-3");

    pthread_join(tid1, nullptr);
    pthread_join(tid2, nullptr);
    pthread_join(tid3, nullptr);

}



//有锁情况抢票
struct ThreadData
{
    ThreadData(const char* name, pthread_mutex_t& mutex)
        :_name(name)
        ,_mutex(&mutex)
    {
        pthread_mutex_init(_mutex, nullptr);
    }

    void Lock()
    {
        pthread_mutex_lock(_mutex);
    }

    void UnLock()
    {
        pthread_mutex_unlock(_mutex);
    }

    ~ThreadData()
    {
        pthread_mutex_destroy(_mutex);
    }

    pthread_t _tid;
    pthread_mutex_t* _mutex;
    std::string _name;
};


void* Routine2(void* args)
{
    ThreadData* t = static_cast<ThreadData*>(args);
    std::cout << "线程: " << t->_name <<" 开始抢票" << std::endl;
    
    while(1)
    {   
        t->Lock();
        if(tickets > 0)
        {
            usleep(100);
            std::cout << "线程" << t->_name << "抢" << tickets << std::endl;
            tickets--;
            t->UnLock();
        }
        else
        {
            t->UnLock();
            break;
        }
    }

    return nullptr;
}


void test02()
{

    pthread_mutex_t mutex;

    ThreadData* t1 = new ThreadData("thread-1", mutex);
    pthread_create(&t1->_tid, nullptr, Routine2, t1);

    ThreadData* t2 = new ThreadData("thread-2", mutex);
    pthread_create(&t2->_tid, nullptr, Routine2, t2);

    ThreadData* t3 = new ThreadData("thread-3", mutex);
    pthread_create(&t3->_tid, nullptr, Routine2, t3);

    pthread_join(t1->_tid, nullptr);
    pthread_join(t2->_tid, nullptr);
    pthread_join(t3->_tid, nullptr);

}



using namespace MutexModlue;

struct ThreadData02
{

    ThreadData02(const char* name, Mutex& mutex)
        :_name(name)
        ,_mutex(&mutex)
    {}

    Mutex* _mutex;
    std::string _name;
};

void* Routine3(void* args)
{
    ThreadData02* t = static_cast<ThreadData02*>(args);
    std::cout << "线程: " << t->_name <<" 开始抢票" << std::endl;
    
    while(1)
    {   
        GuardLock lock(*t->_mutex);
        if(tickets > 0)
        {
            usleep(100);
            std::cout << "线程" << t->_name << "抢" << tickets << std::endl;
            tickets--;
        }
        else
        {
            break;
        }
    }

    return nullptr;
}



void test03()
{

    Mutex mutex;
    pthread_t td1, td2, td3;

    ThreadData02* t1 = new ThreadData02("thread-1", mutex);
    pthread_create(&td1, nullptr, Routine3, t1);

    ThreadData02* t2 = new ThreadData02("thread-2", mutex);
    pthread_create(&td2, nullptr, Routine3, t2);

    ThreadData02* t3 = new ThreadData02("thread-3", mutex);
    pthread_create(&td3, nullptr, Routine3, t3);

    pthread_join(td1, nullptr);
    pthread_join(td2, nullptr);
    pthread_join(td3, nullptr);

}

int main()
{
    //test01();
    //test02();
    test03();
    return 0;
}